<?php
/*
hayphpdb - Simple PHP database Class, originally written for www.wikiportret.nl
Copyright (c) 2008-2009 Hay Kranen <www.haykranen.nl> <hay at bykr dot org>
version 1.0-beta2

== Release Notes ==

=== 1.0-beta2 ===
* Converted code to the Singleton pattern 
  http://www.talkphp.com/advanced-php-programming/1304-how-use-singleton-design-pattern.html
  
== License (MIT/X11) ==

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/

Class db {
    private static $instance;
    private $db = false;
    public  $last_query = '';
    public  $num_rows;
    public  $last_insert_id;
    public  $last_error;
    public  $stripslashes = false;
    public  $debug;
    public  $bailaction = false;
    
    // No __construct or __clone allowed in a Singleton
    private function __construct(){}
    private function __clone(){}
    
    public static function getInstance() {
        if(!self::$instance) self::$instance = new db();
        return self::$instance;
    }
    
    public function isdb() {
        return isset($db);
    }

    public function setup($host, $user, $pass, $database) {
        $this->host = $host;
        $this->user = $user;
        $this->pass = $pass;
        $this->database = $database;
        $this->connect();
    }

    public function select_db($database = false) {
        // only change if a new database is given
        if ($database) $this->database = $database;
        @mysql_select_db($this->database, $this->db) or $this->bail("The database ".$this->database." could not be found. ");
    }

    private function connect() {
        @$this->db = mysql_connect($this->host, $this->user, $this->pass) or $this->bail("Could not connect to database!");
        if(!is_resource($this->db)) $this->bail("Could not get a roper connection");        
        $this->select_db();
    }

    private function query($sql) {
        $this->last_query = $sql;
        @$result = mysql_query($sql);
        if($result) {
            // TODO
            // This is a little risky, because the insert_id() function is
            // run every time a query is done, while it should only happen with INSERT
            // queries
            $this->last_insert_id = @mysql_insert_id($this->db);
            return $result;
        } else {
            $this->last_error = @mysql_error();
            $this->bail();
            return false;
        }
    }

    private function where($where) {
        // Where is an array ("id" => 5, "text" => "foo")
        // or a single value, then it is implied that it should
        // be 'id'
        if(!is_array($where)) $where = array("id" => $where);

        $sql = " WHERE ";
        $i = 0;
        foreach($where as $key=>$value) {
            $sql .= "`".$this->escape($key)."` = '".$this->escape($value)."'";
            if($i < count($where)-1) $sql .= " AND ";
            $i++;
        }
        $sql .= ";";
        return $sql;
    }

    public function select($table, $where = false) {
        $sql = "SELECT * FROM `".$this->escape($table)."`";

        // Add WHERE clause if needed
        if ($where) $sql .= $this->where($where);

        $result = $this->query($sql);
        
        // Add number of rows to the property
        $this->num_rows = @mysql_num_rows($result);
        return $this->convert_to_array($result);
    }

    public function select_single($table, $id) {
        $sql  = "SELECT * FROM `".$this->escape($table)."`";
        $sql .= " WHERE `id`='".$this->escape($id)."' LIMIT 1;";

        $result = $this->query($sql);
        return $this->convert_to_array($result, true);
    }

    public function delete($table, array $where) {
        $sql  = "DELETE FROM `$table`";
        $sql .= $this->where($where);
        return $this->query($sql, false);
    }

    public function insert($table, array $array) {
        $i = 0;
        $max = count($array) - 1;
        $insert = ''; $values = '';
        
        foreach($array as $key=>$value) {
            $insert .= "`".$this->escape($key)."`";
            if ($i < $max) $insert .= ",";
            $values .= "'".$this->escape($value)."'";
            if ($i < $max) $values .= ",";
            $i++;
        }

        // Finally make the sql statement and query it
        $sql = "INSERT INTO `$table` ($insert) VALUES ($values);";
        return $this->query($sql, false);
    }

    public function update($table, array $values, $where) {
        $i = 0;
        $update = "";
        foreach ($values as $key=>$value) {
            $update .= "`".$this->escape($key)."` = '".$this->escape($value)."'";
            if($i < count($values) - 1) $update .= ",";
            $i++;
        }
        $where  = $this->where($where);
        $sql = "UPDATE `$table` SET $update $where";
        return $this->query($sql, false);
    }

    private function convert_to_array($mysql_result, $single = false) {
        if(!$mysql_result) return false;

        if ($single) {
            return mysql_fetch_array($mysql_result, MYSQL_ASSOC);
        } else {
            $array = array();
            while($row = mysql_fetch_array($mysql_result, MYSQL_ASSOC)) {
                // Stupid PHP with its slashes
                if(($this->stripslashes) && get_magic_quotes_gpc()) $row = $this->stripslashes_deep($row);
                $array[] = $row;
            }
            return $array;
        }
    }

    private function escape($value) {
        // Strips slashes and escapes possibile scary characters
        if(get_magic_quotes_gpc()) {
            $value = stripslashes($value);
        }
        $value = htmlentities($value);
        return mysql_real_escape_string($value, $this->db);
    }
    
    private function stripslashes_deep($value) {
        $value = is_array($value) ?
                    array_map('stripslashes_deep', $value) :
                    stripslashes($value);
        return $value;
    }
    
    private function bail($msg = false) {        
        // die with a message
        if($this->debug > 0) {
            if(!$msg) $msg = "<br>Mysql_error: ".$this->last_error."<br>Last query:".$this->last_query;
        }

        if(!$this->bailaction) {
            die($msg);
        } else {
            switch($this->bailaction) {
                case "return_false":
                    die(false);
                    break;
                case "error_array":
                    return array("error" => $msg);
                    break;
            }
        }

    }
} // Class db
?>